package com.ocom.payhandle.fun.impl;

import com.alibaba.fastjson.JSON;
import com.ocom.common.entity.card.*;
import com.ocom.common.entity.company.EntityCompanyConfig;
import com.ocom.common.entity.payconfig.EntityXfDeviceMealConfig;
import com.ocom.common.utils.CommonUtil;
import com.ocom.common.utils.DateUtil;
import com.ocom.common.utils.DateUtils;
import com.ocom.common.utils.ObjectList;
import com.ocom.common.vo.pyhandle.CancelOrderVo;
import com.ocom.payhandle.fun.PayHandleFunService;
import com.ocom.payhandle.service.*;
import com.ocom.payhandle.vo.DeviceInfoVo;
import com.ocom.redis.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Slf4j
@Service
public class PayHandleFunServiceImpl implements PayHandleFunService {

    @Resource
    private RedisUtil redisUtil;

    @Autowired
    DeviceInfoService deviceInfoService;

    @Autowired
    private XfMealTimeService xfMealTimeService;

    @Autowired
    private XfMerchPayInfoService xfMerchPayInfoService;

    @Autowired
    private XfMerchantInfoService xfMerchantInfoService;

    @Autowired
    private XfDeviceMealConfigServcie xfDeviceMealConfigServcie;

    @Autowired
    private XfPointInfoService xfPointInfoService;

    @Autowired
    XfRepairpayConfigService xfRepairpayConfigService;

    @Autowired
    private CompanyConfigService companyConfigService;

    //查询机器和消费时间等参数
    public Integer selectMealNo(Long companyId, Long pointId,Integer accTypeId ,  Date date) {
        //查询收费的和商家信息
        //根据machNo(device_no)查找消费点point_id、商户merch_id
        Long timeLong = Long.valueOf(4 * 60 * 60);
        if(pointId == null )  pointId = 0l;
        if(accTypeId == null )  accTypeId = 0;
        //查询redis是否为空，不为空把值存入redis
        String mealTimeRedis = "xf_meal_time#comId:" + companyId + "#pointId:" + pointId + "#accTypeId:"+accTypeId;
        Object objectMealTime = redisUtil.get(mealTimeRedis);
        List<EntityXfMealTime> mealTimeList = null;
        if (objectMealTime == null) {
            mealTimeList = xfMealTimeService.selectTimeList3(companyId, pointId, accTypeId);

            if (mealTimeList != null) {
                redisUtil.set(mealTimeRedis, mealTimeList, timeLong);
            }
        } else {
            mealTimeList = ObjectList.castList(objectMealTime, EntityXfMealTime.class);
        }
        if (mealTimeList != null) {
            for (EntityXfMealTime entityXfMealTime : mealTimeList) {
                if (DateUtils.isInTimeFor2(date, entityXfMealTime.getBeginTime(), entityXfMealTime.getEndTime())) {
                    return Integer.valueOf(entityXfMealTime.getMealNo());
                }
            }
        }
        return 0;
    }

    //查询通道配置
    public EntiyXfMerchPayInfo selectConfigure(Long comId, Long merchId) {
        EntiyXfMerchPayInfo entiyXfMerchPayInfo = null;
        String xfMerchPayRedis = "xf_merch_pay_info#comId:" + comId + "#merchId:" + merchId + "#";
        Object object = redisUtil.get(xfMerchPayRedis);
        if (null == object){
            entiyXfMerchPayInfo = xfMerchPayInfoService.selectConfigure(comId, merchId);
//            log.info("查找商户支付信息 - 【{}】【{}】【{}】", comId, merchId, entiyXfMerchPayInfo);
            Long timeLong = Long.valueOf(4 * 60 * 60);
            redisUtil.set(xfMerchPayRedis, entiyXfMerchPayInfo, timeLong);
        } else {
            entiyXfMerchPayInfo = JSON.parseObject(JSON.toJSONString(object), EntiyXfMerchPayInfo.class);
//            log.info("redis  解析 Json  - 【{}】 【{}】", object, entiyXfMerchPayInfo);
        }
        return entiyXfMerchPayInfo;
        }

    //查询通道配置
    public EntiyXfMerchPayInfo configure(EntityXfRecordProcess entityXfRecordProcess) {
        EntiyXfMerchPayInfo entiyXfMerchPayInfo = null;
        String xfMerchPayRedis = "xf_merch_pay_info#comId:" + entityXfRecordProcess.getComId() + "#merchId:" + entityXfRecordProcess.getMerchId() + "#";
        Object object = redisUtil.get(xfMerchPayRedis);
        if (entityXfRecordProcess.getOrderNo().startsWith("ZS")) {
            entiyXfMerchPayInfo = xfMerchPayInfoService.selectConfigure(entityXfRecordProcess.getComId(), 0L);
            return entiyXfMerchPayInfo;
        }
        if (object == null) {
            if (entityXfRecordProcess.getPointId() == null || entityXfRecordProcess.getPointId() == 0 || entityXfRecordProcess.getMerchId() == null) {
                entiyXfMerchPayInfo = xfMerchPayInfoService.selectConfigure(entityXfRecordProcess.getComId(), 0L);
            } else {

                //a)pMerID:=merchID，查找商户pMerID有没有支付通道，如果没有找上级商户，直至顶级（pMerID ==0）。
                entiyXfMerchPayInfo = xfMerchPayInfoService.selectConfigure(entityXfRecordProcess.getComId(), entityXfRecordProcess.getMerchId());
                if (entiyXfMerchPayInfo == null) {
                    int parentMerchId = Math.toIntExact(entityXfRecordProcess.getMerchId());
                    for (int i = 0; i < 100; i++) {
                        EntityXfMerchantInfo entityXfMerchantInfo = xfMerchantInfoService.selectParentMerchId(entityXfRecordProcess.getComId(), parentMerchId);
                        if (entityXfMerchantInfo != null && entityXfMerchantInfo.getParentMerchId() != null) {
                            parentMerchId = entityXfMerchantInfo.getParentMerchId();
                            entiyXfMerchPayInfo = xfMerchPayInfoService.selectConfigure(entityXfRecordProcess.getComId(), Long.valueOf(parentMerchId));
                            if (entiyXfMerchPayInfo != null) {
                                break;
                            }
                        }
                        //父级商户id为0不用循环下去了
                        if (parentMerchId == 0) {
                            break;
                        }
                    }
                }
            }
//            log.info("查找商户支付信息 - 【{}】 【{}】", entityXfRecordProcess, entiyXfMerchPayInfo);
            Long timeLong = Long.valueOf(4 * 60 * 60);
            redisUtil.set(xfMerchPayRedis, entiyXfMerchPayInfo, timeLong);
        } else {
            entiyXfMerchPayInfo = JSON.parseObject(JSON.toJSONString(object), EntiyXfMerchPayInfo.class);
//            log.info("redis  解析 Json  - 【{}】 【{}】", object, entiyXfMerchPayInfo);
        }
        return entiyXfMerchPayInfo;
    }


    //查询机器和消费时间等参数
    public void relatedDevice(EntityXfRecordProcess entityXfRecordProcess, Long companyId, String machNo, Date date){
        if (entityXfRecordProcess.getAccTypeId() == null) {
            entityXfRecordProcess.setAccTypeId(0);
        }
        //查询收费的和商家信息
        //根据machNo(device_no)查找消费点point_id、商户merch_id
        if(CommonUtil.isNull(entityXfRecordProcess.getMealNo()))entityXfRecordProcess.setMealNo("0");
        entityXfRecordProcess.setComId(companyId);
        entityXfRecordProcess.setMerchId(0l);
        entityXfRecordProcess.setPointId(0l);
        entityXfRecordProcess.setMealNo("0");
        entityXfRecordProcess.setComId(companyId);
        entityXfRecordProcess.setDeviceNo(machNo);
        Long timeLong= Long.valueOf(4*60*60);
        //查询redis是否为空，不为空把值存入redis
        String deviceInfoVoRedis="xf_device_info#comId:"+companyId+"#machNo:"+machNo+"#";
        Object objectDeviceInfo=redisUtil.get(deviceInfoVoRedis);
        DeviceInfoVo deviceInfoVo=null;
        if (objectDeviceInfo == null) {
            deviceInfoVo=deviceInfoService.selectPointId(companyId,machNo);
            if (deviceInfoVo!=null){
                redisUtil.set(deviceInfoVoRedis, deviceInfoVo,timeLong);
            }
        }else {
            deviceInfoVo =JSON.parseObject(JSON.toJSONString(objectDeviceInfo), DeviceInfoVo.class);
        }

        if (deviceInfoVo!=null){
            entityXfRecordProcess.setDeviceName(deviceInfoVo.getDeviceName());
            entityXfRecordProcess.setPointId(deviceInfoVo.getPointId());
            entityXfRecordProcess.setPointName(deviceInfoVo.getPointName());
            entityXfRecordProcess.setMerchId(deviceInfoVo.getMerchId());
            entityXfRecordProcess.setMerchName(deviceInfoVo.getMerchName());
        }

        //判断消费时间段
        entityXfRecordProcess.setConsTime(date); 

        //查询redis是否为空，不为空把值存入redis
        String mealTimeRedis="xf_meal_time#comId:"+companyId+"#pointId:"+entityXfRecordProcess.getPointId()+"#accTypeId:"+entityXfRecordProcess.getAccTypeId();
        Object objectMealTime=redisUtil.get(mealTimeRedis);
        List<EntityXfMealTime> mealTimeList=null;
        if (objectMealTime == null) {

            mealTimeList=xfMealTimeService.selectTimeList3(companyId,deviceInfoVo.getPointId(),entityXfRecordProcess.getAccTypeId());

            if (mealTimeList!=null){
                redisUtil.set(mealTimeRedis, mealTimeList,timeLong);
            }
        }else {
            mealTimeList =ObjectList.castList(objectMealTime, EntityXfMealTime.class);
        }

        if (mealTimeList != null) {
            for (EntityXfMealTime entityXfMealTime : mealTimeList) {
                if (DateUtils.isInTimeFor2(date,entityXfMealTime.getBeginTime(),entityXfMealTime.getEndTime())){
                    entityXfRecordProcess.setMealNo(entityXfMealTime.getMealNo());
                    break;
                }
            }
        }

        //获取消费种类
        String XfDeviceMealConfigRedis="xf_device_meal_config#comId:"+companyId+"#machNo:"+machNo+"#";
        Object objectXfDeviceMealConfig=redisUtil.get(XfDeviceMealConfigRedis);
        List<EntityXfDeviceMealConfig> deviceMealConfig=null;
        if (objectXfDeviceMealConfig == null) {
            deviceMealConfig=xfDeviceMealConfigServcie.selectVoucher(companyId,machNo);

            if (mealTimeList!=null){
                redisUtil.set(XfDeviceMealConfigRedis, deviceMealConfig,timeLong);
            }
        }else {
            deviceMealConfig =ObjectList.castList(objectXfDeviceMealConfig, EntityXfDeviceMealConfig.class);
        }
        if (deviceMealConfig!=null){
            entityXfRecordProcess.setXfDeviceMealConfigList(deviceMealConfig);
        }
    }

    @Override
    public void relatedReceiptNo(EntityXfRecordProcess entityXfRecordProcess) {
        String date1 = DateUtils.getDate();
        if(entityXfRecordProcess.getConsState()!=null && entityXfRecordProcess.getConsState()==5 && entityXfRecordProcess.getMealDate()!=null){
            date1 = DateUtil.getStrDate2(entityXfRecordProcess.getMealDate(), "yyyy-MM-dd");
        }
        String receiptNoKey = "receiptNo:#comId:"+ entityXfRecordProcess.getComId()+"#pointId:"+ entityXfRecordProcess.getPointId()+"#date:"+date1;
        if(redisUtil.get(receiptNoKey)==null){
            redisUtil.set(receiptNoKey,1000);
        }
        Long receiptNo = redisUtil.incr(receiptNoKey,1l);
        entityXfRecordProcess.setReceiptNo(String.valueOf(receiptNo));
        redisUtil.expire(receiptNoKey,246400l);
    }

    @Override
    public DeviceInfoVo selectDeviceInfo(Long companyId, String machNo){
        Long timeLong= Long.valueOf(4*60*60);
        String deviceInfoVoRedis="xf_device_info#comId:"+companyId+"#machNo:"+machNo+"#";
        Object objectDeviceInfo=redisUtil.get(deviceInfoVoRedis);
        DeviceInfoVo deviceInfoVo=null;
        if (objectDeviceInfo == null) {
            deviceInfoVo=deviceInfoService.selectPointId(companyId,machNo);
            if (deviceInfoVo!=null){
                redisUtil.set(deviceInfoVoRedis, deviceInfoVo,timeLong);
            }
        }else {
            deviceInfoVo =JSON.parseObject(JSON.toJSONString(objectDeviceInfo), DeviceInfoVo.class);
        }
        return  deviceInfoVo;
    }

    @Override
    public Boolean checkCanPay(Integer consType,EntityXfRecordProcess entityXfRecordProcess, EntityXfAccountInfo entityXfAccountInfo) {
        try {
            if (CommonUtil.isNull(entityXfRecordProcess.getMealNo())) {
                return true;
            }
            Integer mealNo = Integer.valueOf(entityXfRecordProcess.getMealNo());
            if (consType != 1) {
                mealNo = 0;
            }
            if (mealNo != null
                    && entityXfRecordProcess.getXfDeviceMealConfigList() != null
                    && entityXfRecordProcess.getXfDeviceMealConfigList().size() > 0) {
                for (EntityXfDeviceMealConfig entityXfDeviceMealConfig : entityXfRecordProcess.getXfDeviceMealConfigList()) {
                    if (mealNo.equals(entityXfDeviceMealConfig.getMealNo())) {
                        if (CommonUtil.isNull(entityXfDeviceMealConfig.getAccountIds())) {
                            return true;
                        }
                        String[] accountIds = entityXfDeviceMealConfig.getAccountIds().split(",");
                        List<String> accountList = Arrays.asList(accountIds);
                        if(accountList.contains(String.valueOf(entityXfAccountInfo.getAccTypeId()))){
                            return true;
                        }else{
                            log.error("【当前人员被禁止消费】【{}】【{}】【{}】",entityXfRecordProcess.getDeviceNo(),entityXfRecordProcess,entityXfDeviceMealConfig);
                            return false;
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("【查找人员是否可以消费】【{}】【{}】【{}】", entityXfRecordProcess, entityXfAccountInfo, e);
        }
        return true;
    }

    @Override
    public void relatedDingCan(EntityXfRecordProcess entityXfRecordProcess, String consDate, Integer consMeal, Integer consPoint) {
        try {
            entityXfRecordProcess.setMealDate(DateUtils.strToDate2(consDate));
            entityXfRecordProcess.setMealNo(consMeal.toString());
            entityXfRecordProcess.setPointId(consPoint.longValue());
            if (consPoint == 0) {
                entityXfRecordProcess.setPointName("订单:本单位");
            } else {
                EntityXfPointInfo entityXfPointInfo = xfPointInfoService.getTollPointInfo(entityXfRecordProcess.getComId(), consPoint);
                entityXfRecordProcess.setPointName("订单:"+entityXfPointInfo.getPointName());
            }
        } catch (Exception e) {
            log.error("【更改订单日期餐段消费点异常】【{}】【{}】【{}】【{}】【{}】", entityXfRecordProcess, consDate, consMeal, consPoint, e);
        }
    }

    //consMeal == -1  仅检查是否开启补缴功能
    @Override
    public boolean checkIfWaitPay(Long companyId,String consMeal,Long merchId) {
        try {
            //判断是否有补缴
            EntityXfRepairpayConfig entityXfRepairpayConfig = xfRepairpayConfigService.getByComId(companyId,merchId);

            if (entityXfRepairpayConfig != null && consMeal.equals("-1")){
                return true;
            }
            if (entityXfRepairpayConfig != null && entityXfRepairpayConfig.getMode() == 1
                    && !CommonUtil.isNull(entityXfRepairpayConfig.getMealNos())) {
                //是否有补缴
                if (entityXfRepairpayConfig.getMealNos().equals("0")) {
                    return true;
                } else {
                    List<String> mealList = Arrays.asList(entityXfRepairpayConfig.getMealNos().split(","));
                    if (mealList.contains(consMeal)) {
                        return true;
                    }
                }
            }
        } catch (Exception e) {
            log.error("查补缴配置异常【{}】【{}】【{}】", companyId, consMeal, e);
        }
        return false;
    }

    //取消参数
    @Override
    public int getCancelConfig(Long companyId, Long opTypeDiff) {
        try {
            if (opTypeDiff == null || opTypeDiff == 0l) return -1;
            //’cancelConfig’,’refPayTimes’
            EntityCompanyConfig entityCompanyConfig1 = companyConfigService.getTapValue(companyId, "cancelConfig");
            if (entityCompanyConfig1 != null) {
                List<CancelOrderVo> list = JSON.parseArray(entityCompanyConfig1.getConfig(), CancelOrderVo.class);
                Map<Integer, Integer> cant = list.stream().collect(Collectors.toMap(e -> e.getOpType(), e -> e.getTimes(), (e1, e2) -> e1));
                if (cant.containsKey(opTypeDiff.intValue())) {
                    return cant.get(opTypeDiff.intValue());
                }
                if (cant.containsKey(-1)) {
                    return cant.get(-1);
                }
            }
        } catch (Exception e) {
            log.error("查取消配置异常【{}】【{}】", companyId, e);
        }
        return -1;
    }

    //取消参数
    @Override
    public int getRefPayTimes(Long companyId) {
        try {
            //’cancelConfig’,’refPayTimes’
            EntityCompanyConfig entityCompanyConfig1 = companyConfigService.getTapValue(companyId, "refPayTimes");
            if (entityCompanyConfig1 != null) {
                return Integer.valueOf(entityCompanyConfig1.getConfig());
            }
        } catch (Exception e) {
            log.error("查第二笔配置异常【{}】【{}】", companyId, e);
        }
        return -1;
    }

}
